package me.jiatao.googlebilling.billing;

import android.app.Activity;
import android.content.Context;
import android.text.TextUtils;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.android.billingclient.api.AcknowledgePurchaseParams;
import com.android.billingclient.api.AcknowledgePurchaseResponseListener;
import com.android.billingclient.api.BillingClient;
import com.android.billingclient.api.BillingClientStateListener;
import com.android.billingclient.api.BillingFlowParams;
import com.android.billingclient.api.BillingResult;
import com.android.billingclient.api.ConsumeParams;
import com.android.billingclient.api.ConsumeResponseListener;
import com.android.billingclient.api.Purchase;
import com.android.billingclient.api.PurchasesResponseListener;
import com.android.billingclient.api.PurchasesUpdatedListener;
import com.android.billingclient.api.SkuDetails;
import com.android.billingclient.api.SkuDetailsParams;
import com.android.billingclient.api.SkuDetailsResponseListener;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


public class GoogleBillingUtil {

    private GoogleBillingUtil() {
    }

    public static final String BILLING_TYPE_INAPP = BillingClient.SkuType.INAPP;//内购
    public static final String BILLING_TYPE_SUBS = BillingClient.SkuType.SUBS;//订阅

    /**
     * 单例模式
     */
    private volatile static GoogleBillingUtil instance;

    public static GoogleBillingUtil getInstance() {
        if (instance == null) {
            synchronized (GoogleBillingUtil.class) {
                if (instance == null) {
                    instance = new GoogleBillingUtil();
                    instance.onGoogleBillingListenerMap = new HashMap<>(5);
                }
            }
        }
        return instance;
    }


    /**
     * google 支付类
     */
    private BillingClient mBillingClient;

    /**
     * 是否自动消耗商品
     * 消耗商品要慎重，一定确保在服务端收到订单完成通知后
     */
    //private boolean isAutoConsume = false;

    /**
     * 是否打印日志
     */
    private boolean isDebug = true;

    /**
     * 记录当前支付方式
     */
    private String currentSkuType = "";

    /**
     * 消耗失败重试次数
     */
    private final int CONSUME_RETRY_TIMES = 3;
    /**
     * 监听列表
     */
    private Map<String, OnGoogleBillingListener> onGoogleBillingListenerMap;

    private void log(String msg) {
        if (isDebug) {
            Log.w("**GoogleBillingUtil**", msg);
        }
    }

    public void isDebug(boolean isDebug) {
        this.isDebug = isDebug;
    }

    /**
     * 初始化基本对象
     *
     * @param context
     */
    public void build(Context context) {
        mBillingClient = BillingClient.newBuilder(context)
                .setListener(new MyPurchasesUpdatedListener())
                .enablePendingPurchases()
                .build();

        //连接到google服务
        startConnection();
    }

    /**
     * 销毁时，移除所有监听
     */
    public void destroy() {
        onGoogleBillingListenerMap.clear();
    }


    /**
     * 连接google服务
     *
     * @return
     */
    private boolean startConnection() {
        if (mBillingClient == null) {
            log("google连接失败: mBillingClient is null");
            return false;
        }
        if (mBillingClient.isReady()) {
            return true;
        } else {
            mBillingClient.startConnection(new MyBillingClientStateListener());
            return false;
        }
    }

    //region ******************** 查询商品信息 ********************

    /**
     * 查询内购商品信息
     */
    public void queryInventoryInApp(ArrayList<String> skuList) {
        queryInventory(skuList, BillingClient.SkuType.INAPP);
    }


    /**
     * 查询订阅商品信息
     */
    public void queryInventorySubs(Activity activity, ArrayList<String> skuList) {
        queryInventory(skuList, BillingClient.SkuType.SUBS);
    }

    private void queryInventory(final ArrayList<String> skuList, final String skuType) {
        if (isListEmpty(skuList)) {
            final BillingResult queryBillingResult = getBillingResult(11, "Query Inventory:sku list is null");
            notifyListener(new IteratorListener() {
                @Override
                public void provideListener(OnGoogleBillingListener listener) {
                    listener.onFail(GoogleBillingListenerTag.QUERY_INVENTORY, queryBillingResult);
                }
            });
            return;
        }

        if (isGoogleConnection()) {
            SkuDetailsParams params = SkuDetailsParams
                    .newBuilder()
                    .setSkusList(skuList)
                    .setType(skuType)
                    .build();
            mBillingClient.querySkuDetailsAsync(params, new MySkuDetailsResponseListener(skuType));
        } else {
            log("queryInventory错误，google服务未连接");
            notifyListener(new IteratorListener() {
                @Override
                public void provideListener(OnGoogleBillingListener listener) {
                    listener.onError(GoogleBillingListenerTag.QUERY_INVENTORY);
                }
            });
        }
    }

    //endregion ******************** 查询商品信息 ********************

    //region ******************** 查询历史支付但未消耗订单 ********************

    /**
     * 查询消耗型订单
     */
    public void queryPurchasesInApp() {
        queryPurchases(BillingClient.SkuType.INAPP);
    }

    /**
     * 查询订阅订单
     */
    public void queryPurchasesSubs() {
        queryPurchases(BillingClient.SkuType.SUBS);
    }

    /**
     * 查询已经购买过但是没有被消耗的商品，可能网络不稳定或者中断导致的未被消耗
     * 如果购买成功没消耗，就去消耗，消耗完成视为完整的流程。
     *
     * @param skuType
     * @return
     */
    private void queryPurchases(String skuType) {
        if (isGoogleConnection()) {
            mBillingClient.queryPurchasesAsync(skuType, new MyPurchasesResponseListener(skuType));
        } else {
            log("queryPurchases错误，google服务未连接");
            notifyListener(new IteratorListener() {
                @Override
                public void provideListener(OnGoogleBillingListener listener) {
                    listener.onError(GoogleBillingListenerTag.QUERY_PURCHASES);
                }
            });
        }
    }

    //endregion ******************** 查询历史支付但未消耗订单 ********************

    //region ******************** 开始支付 ********************

    /**
     * 发起内购
     *
     * @param skuId     google商品号
     * @param accountId google透传字段，这里用于记录本地订单号
     * @param profileId google透传字段，这里用于记录支付包名
     */
    public void purchaseInApp(Activity activity, String skuId, String accountId, String profileId) {
        currentSkuType = BillingClient.SkuType.INAPP;
        purchase(activity, skuId, BillingClient.SkuType.INAPP, accountId, profileId);
    }

    public void purchaseInApp(Activity activity, String skuId) {
        purchaseInApp(activity, skuId, null, null);
    }


    /**
     * 发起订阅
     *
     * @param skuId     google商品号
     * @param accountId google透传字段，这里用于记录本地订单号
     * @param profileId google透传字段，这里用于记录支付包名
     */
    public void purchaseSubs(Activity activity, String skuId, String accountId, String profileId) {
        currentSkuType = BillingClient.SkuType.SUBS;
        purchase(activity, skuId, BillingClient.SkuType.SUBS, accountId, profileId);
    }

    public void purchaseSubs(Activity activity, String skuId) {
        purchaseSubs(activity, skuId, null, null);
    }

    /**
     * 正式支付
     *
     * @param activity
     * @param skuId
     * @param skuType
     * @param accountId
     * @param profileId
     */
    private void purchase(final Activity activity, final String skuId, final String skuType, final String accountId, final String profileId) {
        if (isGoogleConnection()) {
            /**
             * 查询商品信息
             */
            List<String> skuList = new ArrayList<>();
            skuList.add(skuId);
            SkuDetailsParams skuDetailsParams = SkuDetailsParams.newBuilder()
                    .setSkusList(skuList)
                    .setType(skuType)
                    .build();
            mBillingClient.querySkuDetailsAsync(skuDetailsParams, new SkuDetailsResponseListener() {
                @Override
                public void onSkuDetailsResponse(@NonNull final BillingResult billingResult, @Nullable List<SkuDetails> skuDetailsList) {
                    if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {

                        if (isListEmpty(skuDetailsList)) {
                            /**当前商品信息不存在，回调失败*/

                            log("purchase skuDetailsList is null");
                            final BillingResult queryBillingResult = getBillingResult(101, "Purchase Error:sku details is null");
                            notifyListener(new IteratorListener() {
                                @Override
                                public void provideListener(OnGoogleBillingListener listener) {
                                    listener.onFail(GoogleBillingListenerTag.PURCHASE, queryBillingResult);
                                }
                            });

                        } else {
                            /** 商品信息存在，开始支付 */
                            BillingFlowParams.Builder flowParamsBuilder = BillingFlowParams.newBuilder()
                                    .setSkuDetails(skuDetailsList.get(0));
                            //添加自定义订单信息
                            if (!TextUtils.isEmpty(accountId)) {
                                flowParamsBuilder.setObfuscatedAccountId(accountId);
                            }

                            if (!TextUtils.isEmpty(profileId)) {
                                flowParamsBuilder.setObfuscatedProfileId(profileId);
                            }

                            mBillingClient.launchBillingFlow(activity, flowParamsBuilder.build());
                        }
                    } else {
                        notifyListener(new IteratorListener() {
                            @Override
                            public void provideListener(OnGoogleBillingListener listener) {
                                listener.onFail(GoogleBillingListenerTag.PURCHASE, billingResult);
                            }
                        });
                    }
                }
            });

        } else {
            notifyListener(new IteratorListener() {
                @Override
                public void provideListener(OnGoogleBillingListener listener) {
                    listener.onError(GoogleBillingListenerTag.PURCHASE);
                }
            });
        }
    }

    //endregion ******************** 开始支付 ********************

    //region ******************** 消耗商品 ********************

    /**
     * 消耗商品
     * 如果您在三天内未确认购买交易，用户会自动收到退款，并且 Google Play 会撤消该购买交易。
     * 使用 2.0 之前的 Google Play 结算库版本时，不需要确认。
     * <p>
     * 对于消耗型商品，consumeAsync() 方法满足确认要求，并且表明您的应用已授予用户权利。
     * 此外，通过此方法，您的应用可让一次性商品可供再次购买。
     *
     * @param purchaseToken {@link Purchase#getPurchaseToken()}
     * @param index         消耗失败重试次数
     */
    private void consumeAsync(String purchaseToken, int index) {
        if (isGoogleConnection()) {
            ConsumeParams consumeParams = ConsumeParams.newBuilder()
                    .setPurchaseToken(purchaseToken)
                    .build();
            mBillingClient.consumeAsync(consumeParams, new MyConsumeResponseListener(index));
        } else {
            log("consumeAsync错误，google服务未连接");
            notifyListener(new IteratorListener() {
                @Override
                public void provideListener(OnGoogleBillingListener listener) {
                    listener.onError(GoogleBillingListenerTag.CONSUME);
                }
            });
        }
    }

    public void consumeAsync(String purchaseToken) {
        consumeAsync(purchaseToken, 0);
    }

    //endregion ******************** 消耗商品 ********************

    //region ******************** 确认购买 ********************

    /**
     * 如需确认非消耗型商品的购买交易，请使用结算库中的 BillingClient.acknowledgePurchase()
     * 或 Google Play Developer API 中的 Product.Purchases.Acknowledge。
     * <p>
     * 在确认购买交易之前，您的应用应使用 Google Play 结算库中的 isAcknowledged() 方法
     * 或 Google Play Developer API 中的 acknowledgementState 字段检查该购买交易是否已经过确认。
     *
     * @param purchaseToken
     */
    private void acknowledgePurchase(String purchaseToken) {

        if (isGoogleConnection()) {
            AcknowledgePurchaseParams params = AcknowledgePurchaseParams
                    .newBuilder()
                    .setPurchaseToken(purchaseToken)
                    .build();
            mBillingClient.acknowledgePurchase(params, new MyAcknowledgePurchaseResponseListener());
        } else {
            log("acknowledgePurchase错误，google服务未连接");
            notifyListener(new IteratorListener() {
                @Override
                public void provideListener(OnGoogleBillingListener listener) {
                    listener.onError(GoogleBillingListenerTag.ACKNOWLEDGE_PURCHASE);
                }
            });
        }
    }

    //endregion ******************** 确认购买 ********************


    //region ****************************** 设置回调监听 ******************************

    private String getTag(Activity activity) {
        return activity.getLocalClassName();
    }

    public GoogleBillingUtil addOnGoogleBillingListener(Activity activity, OnGoogleBillingListener onGoogleBillingListener) {
        String tag = getTag(activity);
        return addOnGoogleBillingListener(tag, onGoogleBillingListener);
    }


    public GoogleBillingUtil addOnGoogleBillingListener(String tag, OnGoogleBillingListener onGoogleBillingListener) {
        onGoogleBillingListenerMap.put(tag, onGoogleBillingListener);
        return this;
    }

    public void removeOnGoogleBillingListener(Activity activity) {
        String tag = getTag(activity);
        removeOnGoogleBillingListener(tag);
    }

    public void removeOnGoogleBillingListener(String tag) {
        onGoogleBillingListenerMap.remove(tag);
    }

    /**
     * 用于遍历监听器提供回调
     */
    interface IteratorListener {
        void provideListener(OnGoogleBillingListener listener);
    }

    /**
     * 遍历所有监听器并返回，
     * 避免每次回调都需要写循环
     */
    private void notifyListener(IteratorListener iteratorListener) {
        if (iteratorListener == null) {
            return;
        }
        for (Map.Entry<String, OnGoogleBillingListener> next : onGoogleBillingListenerMap.entrySet()) {
            OnGoogleBillingListener listener = next.getValue();
            iteratorListener.provideListener(listener);
        }
    }
    //endregion

    //region ****************************** 工具方法 ******************************

    private boolean isListEmpty(List list) {
        if (list == null || list.isEmpty()) {
            return true;
        }
        return false;
    }

    /**
     * google服务是否连接成功
     *
     * @return
     */
    private boolean isGoogleConnection() {
        if (mBillingClient == null) {
            log("isGoogleConnection  mBillingClient is null");
            return false;
        }
        if (!mBillingClient.isReady()) {
            startConnection();
            return false;
        }

        return true;
    }

    private BillingResult getBillingResult(int code, String msg) {
        return BillingResult
                .newBuilder()
                .setResponseCode(code)
                .setDebugMessage(msg)
                .build();
    }


    //endregion 工具方法

    //region ****************************** 自定义实现类 ******************************

    /**
     * 监听连接google服务状态
     */
    class MyBillingClientStateListener implements BillingClientStateListener {
        @Override
        public void onBillingSetupFinished(final BillingResult billingResult) {
            if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                notifyListener(new IteratorListener() {
                    @Override
                    public void provideListener(OnGoogleBillingListener listener) {
                        listener.onSetupSuccess();
                    }
                });
                //查询已完成订单，以便补单
                queryPurchasesInApp();
                //queryInventorySubs();

            } else {
                log("连接google服务失败--->code:" + billingResult.getResponseCode()
                        + " message:" + billingResult.getDebugMessage());

                notifyListener(new IteratorListener() {
                    @Override
                    public void provideListener(OnGoogleBillingListener listener) {
                        listener.onFail(GoogleBillingListenerTag.SETUP, billingResult);
                    }
                });
            }
        }

        @Override
        public void onBillingServiceDisconnected() {
            log("google服务连接断开");
            notifyListener(new IteratorListener() {
                @Override
                public void provideListener(OnGoogleBillingListener listener) {
                    listener.onBillingServiceDisconnected();
                }
            });
        }
    }

    /**
     * 用于监听商品列表查询结果
     */
    class MySkuDetailsResponseListener implements SkuDetailsResponseListener {
        private String skuType;

        public MySkuDetailsResponseListener(String skuType) {
            this.skuType = skuType;
        }

        @Override
        public void onSkuDetailsResponse(@NonNull final BillingResult billingResult, @Nullable final List<SkuDetails> list) {
            if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                if (isListEmpty(list)) {
                    final BillingResult queryBillingResult = getBillingResult(12, "Query Inventory:sku details is null");
                    notifyListener(new IteratorListener() {
                        @Override
                        public void provideListener(OnGoogleBillingListener listener) {
                            listener.onFail(GoogleBillingListenerTag.QUERY_INVENTORY, queryBillingResult);
                        }
                    });
                } else {
                    notifyListener(new IteratorListener() {
                        @Override
                        public void provideListener(OnGoogleBillingListener listener) {
                            listener.onQuerySuccess(skuType, list);
                        }
                    });
                }
            } else {
                log("Query Inventory Error---> responseCode:" + billingResult.getResponseCode() + ",msg:" + billingResult.getDebugMessage());
                notifyListener(new IteratorListener() {
                    @Override
                    public void provideListener(OnGoogleBillingListener listener) {
                        listener.onFail(GoogleBillingListenerTag.QUERY_INVENTORY, billingResult);
                    }
                });
            }
        }
    }

    /**
     * Google购买商品回调接口
     * 订阅和内购都走这个接口
     */
    class MyPurchasesUpdatedListener implements PurchasesUpdatedListener {
        @Override
        public void onPurchasesUpdated(@NonNull final BillingResult billingResult, @Nullable final List<Purchase> purchaseList) {
            if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {

                if (isListEmpty(purchaseList)) {
                    final BillingResult purchasesResult = getBillingResult(102, "Purchase Error: purchase list is null");
                    notifyListener(new IteratorListener() {
                        @Override
                        public void provideListener(OnGoogleBillingListener listener) {
                            listener.onFail(GoogleBillingListenerTag.PURCHASE, purchasesResult);
                        }
                    });
                } else {
                    notifyListener(new IteratorListener() {
                        @Override
                        public void provideListener(OnGoogleBillingListener listener) {
                            for (Purchase purchase : purchaseList) {
                                if (purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED) {
                                    listener.onPurchaseSuccess(currentSkuType, purchase);
                                }
                            }
                        }
                    });
                }

            } else {
                log("purchase error ---> responseCode:" + billingResult.getResponseCode() + ",msg:" + billingResult.getDebugMessage());
                notifyListener(new IteratorListener() {
                    @Override
                    public void provideListener(OnGoogleBillingListener listener) {
                        listener.onFail(GoogleBillingListenerTag.PURCHASE, billingResult);
                    }
                });
            }
        }
    }


    /**
     * 查询历史订单回调
     */
    class MyPurchasesResponseListener implements PurchasesResponseListener {
        String skuType;

        public MyPurchasesResponseListener(String skuType) {
            this.skuType = skuType;
        }

        @Override
        public void onQueryPurchasesResponse(@NonNull final BillingResult purchasesResult, final List<Purchase> purchaseList) {
            if (purchasesResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                if (isListEmpty(purchaseList)) {
                    //列表为空时说明所有订单都已经完成，不属于异常情况
                    log("Query Purchases:purchase list is null");
                } else {
                    //遍历所有监听者，开始补单
                    notifyListener(new IteratorListener() {
                        @Override
                        public void provideListener(OnGoogleBillingListener listener) {
                            for (Purchase purchase : purchaseList) {
                                //判断当前订单状态为已支付
                                if (purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED) {
                                    listener.onRecheck(skuType, purchase);
                                }
                            }
                        }
                    });
                }
            } else {
                log("Query Purchases Error --->" + purchasesResult.getDebugMessage());
                notifyListener(new IteratorListener() {
                    @Override
                    public void provideListener(OnGoogleBillingListener listener) {
                        listener.onFail(GoogleBillingListenerTag.QUERY_PURCHASES, purchasesResult);
                    }
                });
            }
        }
    }

    /**
     * 消耗型商品确认消耗
     */
    class MyConsumeResponseListener implements ConsumeResponseListener {
        private int index;

        public MyConsumeResponseListener(int index) {
            this.index = index;
        }

        @Override
        public void onConsumeResponse(@NonNull final BillingResult billingResult, @NonNull final String purchaseToken) {
            if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                log("onConsumeResponse success!");
                notifyListener(new IteratorListener() {
                    @Override
                    public void provideListener(OnGoogleBillingListener listener) {
                        listener.onConsumeSuccess(purchaseToken);
                    }
                });

                return;
            }

            log("Consume Error ---> responseCode:" + billingResult.getResponseCode() + ",msg:" + billingResult.getDebugMessage());

            /**
             * 当前支付没有消耗 并且 小于最大支付次数
             * 重新执行消耗操作
             */
            if (billingResult.getResponseCode() != BillingClient.BillingResponseCode.ITEM_NOT_OWNED
                    && index < CONSUME_RETRY_TIMES) {
                consumeAsync(purchaseToken, ++index);
                return;
            }

            //当前商品已经消耗过,活者超过最大重试次数
            notifyListener(new IteratorListener() {
                @Override
                public void provideListener(OnGoogleBillingListener listener) {
                    listener.onFail(GoogleBillingListenerTag.CONSUME, billingResult);
                }
            });
        }
    }

    /**
     * 非消耗型完成购买
     */
    class MyAcknowledgePurchaseResponseListener implements AcknowledgePurchaseResponseListener {

        @Override
        public void onAcknowledgePurchaseResponse(@NonNull final BillingResult billingResult) {
            if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                notifyListener(new IteratorListener() {
                    @Override
                    public void provideListener(OnGoogleBillingListener listener) {
                        listener.onAcknowledgePurchaseSuccess();
                    }
                });
            } else {
                log("Acknowledge Error ---> responseCode:" + billingResult.getResponseCode() + ",msg:" + billingResult.getDebugMessage());
                //消耗失败重试
                notifyListener(new IteratorListener() {
                    @Override
                    public void provideListener(OnGoogleBillingListener listener) {
                        listener.onFail(GoogleBillingListenerTag.ACKNOWLEDGE_PURCHASE, billingResult);
                    }
                });
            }
        }
    }

    /**
     * 支付流程枚举
     */
    public enum GoogleBillingListenerTag {
        /**
         * 连接到google服务阶段
         */
        SETUP("setup"),
        /**
         * 查询商品阶段
         */
        QUERY_INVENTORY("queryInventory"),
        /**
         * 支付阶段
         */
        PURCHASE("purchase"),
        /**
         * 查询未消耗订单
         */
        QUERY_PURCHASES("queryPurchases"),
        /**
         * 确认消耗阶段
         */
        CONSUME("consume"),
        /**
         * 确认购买阶段
         */
        ACKNOWLEDGE_PURCHASE("AcknowledgePurchase");

        public String tag;

        GoogleBillingListenerTag(String tag) {
            this.tag = tag;
        }
    }

//endregion 自定义实现类


}